#-*- coding: utf8 -*-

from tutor.script import *
from tutor.plugin.maple import *
from tutor.plugin.math.functions import minimizer2D

# meta information
meta(author       = 'Fábio Mendes',
     creationdate = datetime(2010, 10, 23),
     status       = 'testing',
     difficulty   = 'easy',
     time         = 10,
     itemtype     = 'test')

# begin question
vars = [x, y]
shuffle(vars)
u, v = vars

# sorteia variáveis que definem a questão
a = oneof(1,-1) * oneof(1,2,3,4,5,6) / M(2)
b = oneof(1,-1) * oneof(1,2,3,4,5,6) / M(2)
c = oneof(1,-1) * oneof(1,2,3,4,5,6) / M(2)
d = oneof(1,-1) * oneof(1,2,3,4,5,6) / M(2)
#a,b,c,d,e,f = M('[a,b,c,d,e,f]')

# define função
func = oneof(1,-1) * u**2 + a * v**2 + b * v*u + c * u + d * v

# gradientes
s=1
grad_ok = [ diff(func, u), diff(func, v) ]
grad_e1 = [ diff(func - b*u*v, u), diff(func - b*u*v, v) ]
grad_e2 = [ diff(func, u) + d*v, diff(func, v) + c*u ]
grad_e3 = [ diff(func - b*u*v, u) + b*u, diff(func - b*u*v, v) + b*v ]
grads = [ grad_ok, grad_e1, grad_e2, grad_e3 ]

# solucoes
sols = [ M.solve(grad, [x, y]) for grad in grads ]
sols = [ tuple(map(M.rhs, sol[0])) for sol in sols ]
print(sols)
good_ans, bad_grad1, bad_grad2, bad_grad3 = sols

question('Encontre o ponto crítico de $$f(x,y) = ', func, '.$$')
multiplechoice()

# choice: (a)
choice_eq(1, good_ans)
explanation('Escolha correta!') 

# choice: (b)
choice_eq(0, bad_grad1)
explanation('Erro de cálculo! Preste atenção ao derivar $xy$') 

# choice: (c)
choice_eq(0, bad_grad2)
explanation('Erro de cálculo! Preste atenção ao derivar $xy$') 

# choice: (d)
choice_eq(0, bad_grad3)
explanation('Erro de cálculo! Preste atenção ao derivar $xy$') 

# choice: (e)
choice(0, 'Não existe ponto crítico.')
explanation('Os pontos críticos são aqueles em que o gradiente se anula. Veja a solução.') 

# determina se o ponto crítico é máximo, mínimo ou sela
wrong_choice = set([ 'ponto de máximo.', 'ponto de mínimo.', 'ponto de sela.' ]) 

# calcula Hessiana
fxx = diff(func, x, x)
fyy = diff(func, y, y)
fxy = diff(func, x, y)
x0, y0 = good_ans
H = M.Matrix(subs(x==x0, y==y0, [ [fxx, fxy], [fxy, fyy] ]))
eig = M('LinearAlgebra:-Eigenvalues')(H)
print(M.evalf(eig))
l1, l2 = eig[1], eig[2]
assert l1 != 0 or l2 != 0

# testa casos
if l1 > 0 and l2 > 0:
    correct_choice =  'ponto de mínimo.'
elif l1 < 0 and l2 < 0:
    correct_choice =  'ponto de máximo.'
else:
    correct_choice =  'ponto de sela.'
wrong_choice.discard(correct_choice)

question('Caso o ponto crítico exista, ele é um')
multiplechoice()
choice(1, correct_choice)
choice(0, wrong_choice.pop())
choice(0, wrong_choice.pop())
assert not wrong_choice

end()